/*
 * Powered By XY
 * Since 2020
 */

package com.xy.biz.mes.manager.impl;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import com.xy.biz.mes.dao.ManufactureResultDao;
import com.xy.biz.mes.dao.ManufactureResultGoodsDao;
import com.xy.biz.mes.domain.bo.*;
import com.xy.biz.mes.domain.converter.ManufactureResultGoodsConverter;
import com.xy.biz.mes.domain.enums.ManufactureOrderStatusEnum;
import com.xy.biz.mes.domain.enums.ManufactureTaskStatusEnum;
import com.xy.biz.mes.domain.po.ManufactureResultGoodsPO;
import com.xy.biz.mes.domain.query.ManufactureResultGoodsQuery;
import com.xy.biz.mes.domain.query.ManufactureResultQuery;
import com.xy.biz.mes.manager.ManufactureOrderManager;
import com.xy.biz.mes.manager.ManufactureResultManager;
import com.xy.biz.mes.manager.ManufactureTaskManager;
import com.xy.tool.context.UserContextHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.xy.biz.mes.domain.converter.ManufactureResultConverter;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

/**
 *
 *
 * @author zgy
 * @date 2022-2-11
 */
@Service
public class ManufactureResultManagerImpl implements ManufactureResultManager {

    @Autowired
    private ManufactureTaskManager manufactureTaskManager;
    @Autowired
    private ManufactureResultDao manufactureResultDao;
    @Autowired
    private ManufactureResultGoodsDao manufactureResultGoodsDao;

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public int saveManufactureResult(ManufactureResultBO manufactureResultBO) {
        int row = manufactureResultDao.saveManufactureResult(ManufactureResultConverter.toPO(manufactureResultBO));
        if (row > 0) {
            List<ManufactureResultGoodsBO> manufactureResultGoodsList = manufactureResultBO.getManufactureResultGoodsList();
            if (!CollectionUtils.isEmpty(manufactureResultGoodsList)) {
                saveAllManufactureResultGoods(manufactureResultGoodsList);
            }
        }
        return row;
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public int saveAllManufactureResult(Collection<ManufactureResultBO> collection) {
        int row = manufactureResultDao.saveAllManufactureResult(ManufactureResultConverter.toPO(collection));
        if (row > 0) {
            List<ManufactureResultGoodsBO> manufactureResultGoodsList = collection.stream()
                    .filter(e -> !CollectionUtils.isEmpty(e.getManufactureResultGoodsList()))
                    .flatMap(e -> e.getManufactureResultGoodsList().stream())
                    .collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(manufactureResultGoodsList)) {
                row += saveAllManufactureResultGoods(manufactureResultGoodsList);
            }
        }
        return row;
    }

    @Transactional(rollbackFor = RuntimeException.class)
    int saveAllManufactureResultGoods(Collection<ManufactureResultGoodsBO> collection) {
        int row = manufactureResultGoodsDao.saveAllManufactureResultGoods(ManufactureResultGoodsConverter.toPO(collection));
        if (row > 0) {
//            Set<Long> orderIdSet = collection.stream()
//                    .map(ManufactureResultGoodsBO::getManufactureOrderId)
//                    .collect(Collectors.toSet());
//            List<ManufactureOrderBO> manufactureOrderBOList = new ArrayList<>();
//            orderIdSet.forEach(e -> {
//                ManufactureOrderBO order = new ManufactureOrderBO();
//                order.setManufactureOrderId(e);
//                order.setStatus(ManufactureOrderStatusEnum.FINISHED.getCode());
//                manufactureOrderBOList.add(order);
//            });
//            if (!CollectionUtils.isEmpty(manufactureOrderBOList)) {
//                row += manufactureOrderManager.updateAllManufactureOrder(manufactureOrderBOList);
//            }
            Set<ManufactureTaskGoodsBO> manufactureTaskGoodsBOSet = collection.stream()
                    .filter(e -> Objects.nonNull(e.getManufactureTaskGoodsBO()))
                    .flatMap(e -> Stream.of(e.getManufactureTaskGoodsBO()))
                    .collect(Collectors.toSet());
            List<ManufactureTaskGoodsBO> manufactureTaskBOList = new ArrayList<>();
            manufactureTaskGoodsBOSet.forEach(e -> {
                ManufactureTaskGoodsBO taskGoodsBO = new ManufactureTaskGoodsBO();
                taskGoodsBO.setManufactureTaskGoodsId(e.getManufactureTaskGoodsId());
                taskGoodsBO.setFromStatusSet(e.getFromStatusSet());
                taskGoodsBO.setHandOverResult(e.getHandOverResult());
                taskGoodsBO.setUpdateTime(LocalDateTime.now());
                manufactureTaskBOList.add(taskGoodsBO);
            });
            if (!CollectionUtils.isEmpty(manufactureTaskBOList)) {
                int affectRows = manufactureTaskManager.updateAllManufactureTaskGoodsResult(manufactureTaskBOList);
                if (affectRows == 0) {
                    throw new RuntimeException("affect rows is 0");
                }
            }
        }
        return row;
    }

    @Override
    public int updateManufactureResult(ManufactureResultBO manufactureResultBO) {
        return manufactureResultDao.updateManufactureResult(ManufactureResultConverter.toPO(manufactureResultBO));
    }

    @Override
    public int deleteManufactureResult(java.lang.Long manufactureResultId) {
        return manufactureResultDao.deleteManufactureResult(manufactureResultId);
    }

    @Override
    public ManufactureResultBO getManufactureResult(java.lang.Long manufactureResultId) {
        return ManufactureResultConverter.fromPO(manufactureResultDao.getManufactureResult(manufactureResultId));
    }

    @Override
    public List<ManufactureResultBO> listManufactureResultById(Collection<java.lang.Long> collection) {
        return ManufactureResultConverter.fromPO(manufactureResultDao.listManufactureResultById(collection));
    }

    @Override
    public List<ManufactureResultBO> listManufactureResult(ManufactureResultQuery query) {
        List<ManufactureResultBO> manufactureResultBOList =
                ManufactureResultConverter.fromPO(manufactureResultDao.listManufactureResult(query));
        build(query.getWithGoodsFlag(), manufactureResultBOList);
        return manufactureResultBOList;
    }

    @Override
    public List<ManufactureResultGoodsBO> listManufactureResultGoods(ManufactureResultQuery query) {
        if (!CollectionUtils.isEmpty(query.getManufactureTaskIdList())) {
            List<ManufactureResultGoodsPO> manufactureResultGoodsPOList = manufactureResultGoodsDao.listManufactureResultGoods(ManufactureResultGoodsQuery.max()
                    .manufactureTaskIdList(query.getManufactureTaskIdList()).build());
            return ManufactureResultGoodsConverter.fromPO(manufactureResultGoodsPOList);
        }
        return Collections.emptyList();
    }

    private void build(boolean withGoodsFlag, List<ManufactureResultBO> manufactureResultBOList) {
        if (CollectionUtils.isEmpty(manufactureResultBOList) || !withGoodsFlag) {
            return;
        }
        Set<Long> manufacturerResultIdSet = manufactureResultBOList.stream().map(ManufactureResultBO::getManufactureResultId).collect(Collectors.toSet());
        List<ManufactureResultGoodsBO> manufactureResultGoodsBOList = ManufactureResultGoodsConverter.fromPO(manufactureResultGoodsDao.listManufactureResultGoods(ManufactureResultGoodsQuery.max()
                .manufactureResultIdList(new ArrayList<>(manufacturerResultIdSet))
                .build()));
        if (CollectionUtils.isEmpty(manufactureResultGoodsBOList)) {
            return;
        }
        Map<Long, List<ManufactureResultGoodsBO>> resultGoodsGroup =
                manufactureResultGoodsBOList.stream().collect(Collectors.groupingBy(ManufactureResultGoodsBO::getManufactureResultId));
        manufactureResultBOList.forEach(e -> {
            if (resultGoodsGroup.containsKey(e.getManufactureResultId())) {
                e.setManufactureResultGoodsList(resultGoodsGroup.get(e.getManufactureResultId()));
            }
        });
    }

    @Override
    public int countManufactureResult(ManufactureResultQuery query) {
        return manufactureResultDao.countManufactureResult(query);
    }

}
